package tp.pr5.instructions;

import tp.pr5.NavigationModule;
import tp.pr5.RobotEngine;
import tp.pr5.instructions.exceptions.InstructionExecutionException;
import tp.pr5.instructions.exceptions.WrongInstructionFormatException;
import tp.pr5.items.Item;
import tp.pr5.items.ItemContainer;

public class OperateInstruction extends UndoAble{
	private String objeto;
	RobotEngine rbt;
	NavigationModule nvm;
	ItemContainer rbtCont;
	/*
	 * undo params
	 */
	Item lastItem;
	
	public OperateInstruction(String objeto) {
		this.objeto = objeto;
	}

	public OperateInstruction() {
		this.objeto = null;
	}

	@Override
	public Instruction parse(String cad) throws WrongInstructionFormatException {
		String[] lineArr = cad.trim().replaceAll(" +", " ").split(" ");	//parte la cadena introducida en palabras
		
		
			String accion = "";
			String id = "";
			if(lineArr.length>=1) accion = lineArr[0]; //si existe alguna palabra, la primera serÃ¡ la acciÃ³n
			if(lineArr.length==2) id = lineArr[1]; //si hay mÃ¡s de una palabra, la segunda serÃ¡ la rotaciÃ³n
			
			if(accion.equalsIgnoreCase("OPERATE") || accion.equalsIgnoreCase("OPERAR")){//si la acciÃ³n introducida es OPERATE
				if(id != "") return new OperateInstruction(id);
				else{
					throw new WrongInstructionFormatException();
				}
			}else{
				throw new WrongInstructionFormatException();
			}		
		
	}

	@Override
	public String getHelp() {
		return "     OPERATE|OPERAR <ITEM>";
	}

	@Override
	public void configureContext(RobotEngine engine,
			NavigationModule navigation, ItemContainer robotContainer) {
		this.rbt = engine;
		this.rbtCont = robotContainer;
		this.nvm = navigation;
	}

	@Override
	public void execute() throws InstructionExecutionException {	
		
		if (this.rbtCont.containsItem(objeto)){//si encuentra el item pedido
			this.lastItem = this.rbtCont.getItem(objeto);
				if(!this.rbtCont.getItem(objeto).use(this.rbt, this.nvm)){//si no logra usarlo					
					throw new InstructionExecutionException("WALL·E says: I have problems using the object "+objeto);
				}else{
					//quitar el elemento desde aquÃ­
					if (!this.rbtCont.getItem(objeto).canBeUsed()){
						this.rbtCont.useItem(this.rbtCont.pickItem(objeto));
						this.rbt.emitInventoryChanged("WALL·E says: What a pity, i have no more "+objeto);
						
					}else{
						this.rbt.emitInventoryChanged("");
					}					
					this.rbt.emitRobotUpdate();
				}
		}else{//si no encuentra el item pedido			
			throw new InstructionExecutionException("WALL·E> You do not have any "+objeto+".");
		}
		
	}
	
	@Override
	public boolean isUndoAble() {
		return true;
	}
	/**
	 * revets the las instruction
	 * @throws InstructionExecutionException 
	 */
	public void undo() throws InstructionExecutionException {
		if (this.lastItem != null){//si encuentra el item pedido			
				if(!this.lastItem.unUse(this.rbt, this.nvm)){//si no logra usarlo					
					throw new InstructionExecutionException();
				}else{
					//devolver el elemento		
					if(!this.rbtCont.containsItem(this.lastItem.getId())){						
						this.rbtCont.addItem(this.lastItem);
					}
				}
				this.rbt.emitRobotUpdate();
				this.rbt.emitInventoryChanged("");
		}else{//si no encuentra el item pedido			
			throw new InstructionExecutionException("WALL·E says: I have not such object");
		}	
	}

}
